home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Games / SprocketInvaders / Source / EventHandler.c < prev    next >
Encoding:
Text File  |  2000-09-28  |  10.2 KB  |  501 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        EventHandler.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                xxx put dri here xxx
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            xxx put technology here xxx
  17.  
  18.     Writers:
  19.  
  20.         (cjd)    Chris DeSalvo
  21.         (sjb)    Steve Bollinger
  22.         (BWS)    Brent Schorsch
  23.  
  24.     Change History (most recent first):
  25.  
  26.       <SP21>    10/20/98    BWS        Pause and Quit are now separate needs
  27.         <20>      7/1/98    cjd        Added CPU load axis to InputSprocket data set
  28.         <19>     6/18/98    sjb        InputSprocket.h comes from <> place
  29.         <18>     6/12/98    BWS        Changed to use InputSprocket 68k
  30. */
  31.  
  32. //•    ------------------------------------------------------------------------------------------    •
  33. //•
  34. //•    Copyright © 1996 Apple Computer, Inc., All Rights Reserved
  35. //•
  36. //•
  37. //•        You may incorporate this sample code into your applications without
  38. //•        restriction, though the sample code has been provided "AS IS" and the
  39. //•        responsibility for its operation is 100% yours.  However, what you are
  40. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  41. //•        after having made changes. If you're going to re-distribute the source,
  42. //•        we require that you make it clear in the source that the code was
  43. //•        descended from Apple Sample Code, but that you've made changes.
  44. //•
  45. //•        Authors:
  46. //•            Chris De Salvo
  47. //•            Michael Evans
  48. //•
  49. //•    ------------------------------------------------------------------------------------------    •
  50.  
  51. //•    ------------------------------    Includes
  52.  
  53. #include <DiskInit.h>
  54. #include <ToolUtils.h>
  55.  
  56. #define USE_OLD_ISPNEED_STRUCT            0
  57. #define USE_OLD_INPUT_SPROCKET_LABELS    0
  58.  
  59. #include <DrawSprocket.h>
  60. #include <InputSprocket.h>
  61.  
  62. #include "ErrorHandler.h"
  63. #include "EventHandler.h"
  64. #include "Graphics.h"
  65. #include "MenuHandler.h"
  66. #include "SprocketInvaders.h"
  67.  
  68. //•    ------------------------------    Private Definitions
  69. //•    ------------------------------    Private Types
  70. //•    ------------------------------    Private Variables
  71.  
  72. static SInt32     gEventTime;
  73. static SInt16    gSleepTime;
  74.  
  75. //•    ------------------------------    Private Functions
  76.  
  77. static void EventDispatch(EventRecord *theEvent);
  78. static Boolean DefaultMouseDown(EventRecord *theEvent);
  79. static Boolean DefaultKeyDown(EventRecord *theEvent);
  80. static Boolean DoDiskEvent(EventRecord *theEvent);
  81. static void DoSuspend(void);
  82.  
  83. //•    ------------------------------    Public Variables
  84.  
  85. Boolean                gDone = false;
  86. SInt32                gDeltaTime;
  87. EventHandlerSet        gEventHandlers;
  88. ISpElementReference    gInputElements[numInputs];
  89. GameKeys            gGameKeys;
  90.  
  91. //•    --------------------    EventInit
  92.  
  93. short
  94. EventInit(void)
  95. {
  96. SInt16        modifiers = 0;
  97. EventRecord    dummy;
  98. OSStatus    theError;
  99.  
  100. //•    This structure defines the input needs that we'll be requesting from InputSprocket
  101. ISpNeed        myNeeds[numInputs] =
  102. {
  103.     {
  104.         "\pPlayer 1 Movement",
  105.         200,
  106.         1,
  107.         0,
  108.         kISpElementKind_Axis,
  109.         kISpElementLabel_Axis_XAxis,
  110.         0,
  111.         0,
  112.         0,
  113.         0
  114.     },
  115.     {
  116.         "\pPlayer 1 Fire",
  117.         201,
  118.         1,
  119.         0,
  120.         kISpElementKind_Button,
  121.         kISpElementLabel_Btn_Fire,
  122.         0,
  123.         0,
  124.         0,
  125.         0
  126.     },
  127.     {
  128.         "\pPlayer 2 Movement",
  129.         203,
  130.         2,
  131.         0,
  132.         kISpElementKind_Axis,
  133.         kISpElementLabel_Axis_XAxis,
  134.         0,
  135.         0,
  136.         0,
  137.         0
  138.     },
  139.     {
  140.         "\pPlayer 2 Fire",
  141.         204,
  142.         2,
  143.         0,
  144.         kISpElementKind_Button,
  145.         kISpElementLabel_Btn_Fire,
  146.         0,
  147.         0,
  148.         0,
  149.         0
  150.     },
  151.     {
  152.         "\pAbort Game",
  153.         202,
  154.         0,
  155.         0,
  156.         kISpElementKind_Button,
  157.         kISpElementLabel_Btn_Quit,
  158.         0,
  159.         0,
  160.         0,
  161.         0
  162.     },
  163.     {
  164.         "\pToggle Sound",
  165.         205,
  166.         0,
  167.         0,
  168.         kISpElementKind_Button,
  169.         kISpElementLabel_None,
  170.         kISpNeedFlag_Utility,
  171.         0,
  172.         0,
  173.         0
  174.     },
  175.     {
  176.         "\pSoundSprocket CPU Load",
  177.         206,
  178.         0,
  179.         0,
  180.         kISpElementKind_Axis,
  181.         kISpElementLabel_None,
  182.         0,
  183.         0,
  184.         0,
  185.         0
  186.     }
  187. };
  188.  
  189.     EventAvail(everyEvent, &dummy);
  190.     modifiers |= dummy.modifiers;
  191.     EventAvail(everyEvent, &dummy);
  192.     modifiers |= dummy.modifiers;
  193.     EventAvail(everyEvent, &dummy);
  194.     modifiers |= dummy.modifiers;
  195.  
  196.     RegisterEventHandlers(DefaultKeyDown, DefaultKeyDown, DefaultMouseDown, nil, nil);
  197.     gEventHandlers.diskHandler = DoDiskEvent;
  198.  
  199.     //•    This sets up how often we'll call WaitNextEvent() in out event loop.
  200.     //•    WNE is still emulated so it's sort of a time waster if you call it too often.
  201.     //•    So, we check DblTime which is the user-selected double-click speed.  We make sure
  202.     //•    that we check inputs at least often enough to notice double-clicks.
  203.     gEventTime = GetDblTime();
  204.     gEventTime /= 2;
  205.  
  206.     //•    This is how much time we'll give to background apps when we're not actively playing
  207.     //•    a game.
  208.     gSleepTime = 32767;
  209.  
  210.     //•    Setup the input sprocket elements
  211.     theError = ISpElement_NewVirtualFromNeeds(numInputs, myNeeds, gInputElements, 0);
  212.     if (theError)
  213.         FatalError("Could not create ISp virtual controls from needs.");
  214.  
  215.     //•    Init InputSprocket and tell it our needs
  216.     theError = ISpInit(numInputs, myNeeds, gInputElements, 'SInv', '0002', 0, 128, 0);
  217.     if (theError)
  218.         FatalError("Could not initialize ISp.");
  219.  
  220.     //•    Turn on the keyboard and mouse handlers
  221.     ISpDevices_ActivateClass (kISpDeviceClass_Keyboard);
  222.     ISpDevices_ActivateClass (kISpDeviceClass_Mouse);
  223.     ISpDevices_ActivateClass (kISpDeviceClass_SpeechRecognition);
  224.  
  225.     ISpSuspend ();
  226.  
  227.     return (modifiers);
  228. }
  229.  
  230. //•    --------------------    EventLoop
  231.  
  232. void
  233. EventLoop(void)
  234. {
  235. EventRecord    theEvent;
  236.  
  237. static SInt32    lastTime = 0L;
  238.  
  239. SInt32            thisTime;
  240. Boolean            wasProcessed;
  241.  
  242.     while (false == gDone)
  243.     {
  244.         thisTime = TickCount();
  245.  
  246.         //•    We don't call WNE while we're playing the game
  247.         if (false == gGameInProgress)
  248.         {
  249.             if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, nil))
  250.             {
  251.                 //•    See if DrawSprocket wants to handle this event
  252.                 DSpProcessEvent(&theEvent, &wasProcessed);
  253.  
  254.                 //•    If DSp punted then we process the event
  255.                 if (false == wasProcessed)
  256.                     EventDispatch(&theEvent);
  257.             }
  258.             else
  259.             {
  260.                 //•    Run any idle tasks
  261.                 if (gEventHandlers.idleHandler)
  262.                 {
  263.                     (*gEventHandlers.idleHandler)(&theEvent);
  264.                 }
  265.             }
  266.         }
  267.  
  268.         //•    gDeltaTime tells the game engine how much time has passed since the last
  269.         //•    game loop.
  270.         if (lastTime > 0)
  271.             gDeltaTime = thisTime - lastTime;
  272.  
  273.         //•    We must tell it that at least SOME time has passed.
  274.         if (gDeltaTime < 1)
  275.             gDeltaTime = 1;
  276.  
  277.         if (gGameInProgress)
  278.         {
  279.             ISpTickle();
  280.             GameLoop();
  281.         }
  282.  
  283.         lastTime = TickCount();
  284.     }
  285. }
  286.  
  287. //•    --------------------    EventDispatch
  288.  
  289. static void
  290. EventDispatch(EventRecord *theEvent)
  291. {
  292.     switch (theEvent->what)
  293.     {
  294.         case mouseDown:
  295.             if (gEventHandlers.clickHandler != nil)
  296.                 if ((*gEventHandlers.clickHandler)(theEvent))
  297.                 {
  298.                     break;
  299.                 }
  300.  
  301.             DefaultMouseDown(theEvent);
  302.             break;
  303.  
  304.         case keyDown:
  305.             if (gEventHandlers.keyHandler != nil)
  306.                 if ((*gEventHandlers.keyHandler)(theEvent))
  307.                 {
  308.                     break;
  309.                 }
  310.  
  311.             DefaultKeyDown(theEvent);
  312.             break;
  313.  
  314.         case autoKey:
  315.             if (gEventHandlers.autoKeyHandler != nil)
  316.                 if ((*gEventHandlers.autoKeyHandler)(theEvent))
  317.                 {
  318.                     break;
  319.                 }
  320.  
  321.             DefaultKeyDown(theEvent);
  322.             break;
  323.  
  324.         case updateEvt:
  325.             if (gEventHandlers.updateHandler != nil)
  326.             {
  327.                 if ((*gEventHandlers.updateHandler)(theEvent))
  328.                 {
  329.                 }
  330.             }
  331.  
  332.             BeginUpdate((WindowRef) theEvent->message);
  333.             GraphicsDoUpdateEvent();
  334.             EndUpdate((WindowRef) theEvent->message);
  335.             break;
  336.  
  337.         case diskEvt:
  338.             if (gEventHandlers.diskHandler != nil)
  339.                 (*gEventHandlers.diskHandler)(theEvent);
  340.             break;
  341.  
  342.         case osEvt:
  343.             if (theEvent->message & 0x01000000)        //•    Suspend/resume event
  344.             {
  345.                 if (theEvent->message & 0x00000001)    //•    Resume
  346.                 {
  347.                 }
  348.                 else
  349.                 {
  350.                     DoSuspend();                    //•    Suspend
  351.                 }
  352.             }
  353.             break;
  354.  
  355.         case kHighLevelEvent:
  356.             AEProcessAppleEvent(theEvent);
  357.             break;
  358.     }
  359. }
  360.  
  361. //•    ------------------------------    DefaultMouseDown
  362.  
  363. static Boolean
  364. DefaultMouseDown(EventRecord *theEvent)
  365. {
  366. SInt16        whatPart;
  367. SInt32        menuResult;
  368. WindowRef    whichWindow;
  369.  
  370.     whatPart = FindWindow(theEvent->where, &whichWindow);
  371.  
  372.     switch (whatPart)
  373.     {
  374.         case inGoAway:
  375.             break;
  376.  
  377.         case inMenuBar:
  378.             DrawMenuBar();
  379.             menuResult = MenuSelect(theEvent->where);
  380.  
  381.             if (HiWord(menuResult) != 0)
  382.                 MenuDoChoice(menuResult);
  383.             break;
  384.  
  385.         case inSysWindow:
  386.             SystemClick(theEvent, whichWindow);
  387.             break;
  388.     }
  389.  
  390.     return (true);
  391. }
  392.  
  393. //•    ------------------------------    DefaultKeyDown
  394.  
  395. static Boolean
  396. DefaultKeyDown(EventRecord *theEvent)
  397. {
  398. SInt8    theKey;
  399. SInt8    theCode;
  400. SInt32    menuResult;
  401.  
  402.     theKey = theEvent->message & charCodeMask;
  403.     theCode = (theEvent->message & keyCodeMask) >> 8;
  404.     if ((theEvent->modifiers & cmdKey) != 0)
  405.     {
  406.         menuResult = MenuKey(theKey);
  407.         if (HiWord(menuResult) != 0)
  408.             MenuDoChoice(menuResult);
  409.  
  410.         return (true);
  411.     }
  412.     
  413.     if ('e' == theKey)
  414.         GraphicsDoUpdateEvent();
  415.     
  416.     return (true);
  417. }
  418.  
  419. //•    ------------------------------    DoDiskEvent
  420.  
  421. static Boolean
  422. DoDiskEvent(EventRecord *theEvent)
  423. {
  424. Point    thePoint;
  425. SInt16    value;
  426.  
  427.     if (theEvent->message & 0xFFFF0000)        //•    Error mounting disk
  428.     {
  429.         SetPt(&thePoint, 100, 100);
  430.         value = DIBadMount(thePoint, theEvent->message);
  431.     }
  432.  
  433.     return (true);
  434. }
  435.  
  436. //•    ------------------------------    RegisterEventHandlers
  437.  
  438. void
  439. RegisterEventHandlers(EventHandlerProc keyDown, EventHandlerProc autoKey, EventHandlerProc mouseDown,
  440.                     EventHandlerProc update, EventHandlerProc idle)
  441. {
  442.     gEventHandlers.keyHandler = keyDown;
  443.     gEventHandlers.autoKeyHandler = autoKey;
  444.     gEventHandlers.clickHandler = mouseDown;
  445.     gEventHandlers.updateHandler = update;
  446.     gEventHandlers.idleHandler = idle;
  447. }
  448.  
  449. //•    ------------------------------    ModifyEventHandlers
  450.  
  451. void
  452. ModifyEventHandlers(EventHandlerProc keyDown, EventHandlerProc autoKey, EventHandlerProc mouseDown,
  453.                     EventHandlerProc update, EventHandlerProc idle)
  454. {
  455.     if (keyDown)
  456.         gEventHandlers.keyHandler = keyDown;
  457.  
  458.     if (autoKey)
  459.         gEventHandlers.autoKeyHandler = autoKey;
  460.  
  461.     if (mouseDown)
  462.         gEventHandlers.clickHandler = mouseDown;
  463.  
  464.     if (update)
  465.         gEventHandlers.updateHandler = update;
  466.  
  467.     if (idle)
  468.         gEventHandlers.idleHandler = idle;
  469. }
  470.  
  471. //•    --------------------    DoSuspend
  472. //•
  473. //•    This is a small, local event loop.  All it does is fetch screen update
  474. //•    events and wait to get put back in the foreground.
  475.  
  476. static void
  477. DoSuspend(void)
  478. {
  479. EventRecord    theEvent;
  480.  
  481.     while (true)
  482.     {
  483.         //•    Only check for resume and update events.  While doing so, give TONS of time to other apps
  484.         if (WaitNextEvent(osMask, &theEvent, 32767, nil))
  485.         {
  486.             if (theEvent.message & 0x01000000)        //•    Suspend/resume event
  487.             {
  488.                 if (theEvent.message & 0x00000001)    //•    Resume
  489.                 {
  490.                 Boolean    dummy;
  491.  
  492.                     //•    Make sure that DrawSprocket knows that we've resumed
  493.                     DSpProcessEvent(&theEvent, &dummy);
  494.                 }
  495.                 break;
  496.             }
  497.         }
  498.     }
  499. }
  500.  
  501.